home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / unixSyscall / socket.patch < prev    next >
Text File  |  1991-04-23  |  29KB  |  1,153 lines

  1. /* 
  2.  * socket.c --
  3.  *
  4.  *    Routines to emulate 4.3 BSD socket-related system calls for IPC
  5.  *    using the Internet protocol suite. The routines make calls to 
  6.  *    the Sprite Internet Server using Sprite system calls.
  7.  *
  8.  * Copyright 1987 Regents of the University of California
  9.  * All rights reserved.
  10.  */
  11.  
  12. #ifndef lint
  13. static char rcsid[] = "$Header: /sprite/src/lib/c/unixSyscall/RCS/socket.c,v 1.11 89/09/12 11:43:48 nelson Exp Locker: shirriff $ SPRITE (Berkeley)";
  14. #endif not lint
  15.  
  16. #include <sprite.h>
  17. #include <bit.h>
  18. #include <dev/net.h>
  19. #include <fs.h>
  20. #include <inet.h>
  21. #include <status.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <sys.h>
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include <sys/uio.h>
  28. #include <netinet/in.h>
  29. #include <errno.h>
  30.  
  31. #include "compatInt.h"
  32.  
  33. static ReturnStatus Wait();
  34.  
  35. #ifdef DEBUG
  36. #  define    DebugMsg(status, string)     Stat_PrintMsg(status, string)
  37. #else
  38. #  define    DebugMsg(status, string)    ;
  39. #endif
  40.  
  41. static Boolean    gotHostName = FALSE;
  42. static char     myHostName[100];
  43. static char     streamDevice[100];
  44. static char     dgramDevice[100];
  45. static char     rawDevice[100];
  46.  
  47.  
  48. /*
  49.  *----------------------------------------------------------------------
  50.  *
  51.  * accept --
  52.  *
  53.  *    Accept a stream connection request. This call will create a new
  54.  *    connection to the Inet server upon notification that a remote
  55.  *    connection request is pending.
  56.  *
  57.  *    If the socket is non-blocking and no remote connection requests are
  58.  *    pending, EWOULDBLOCK is returned. If the socket is blockable,
  59.  *    this routine will wait until a remote connection request arrives.
  60.  *
  61.  * Results:
  62.  *    If > 0, the stream ID of the new connection.
  63.  *    If UNIX_ERROR, errno = 
  64.  *    EINVAL        - Bad size for *namePtr.
  65.  *    EWOULDBLOCK    - Non pending requests.
  66.  *
  67.  * Side effects:
  68.  *    A new stream is created.
  69.  *
  70.  *----------------------------------------------------------------------
  71.  */
  72.  
  73. int
  74. accept(socketID, addrPtr, addrLenPtr)
  75.     int            socketID;    /* Socket to listen on. */
  76.     struct sockaddr_in    *addrPtr;    /* Address of newly-accepted 
  77.                      * connection. (out) */
  78.     int            *addrLenPtr;    /* Size of *addrPtr. (in/out) */
  79. {
  80.     ReturnStatus    status;
  81.     int            newSocket;
  82.     ClientData        acceptToken;
  83.     int            addrLen;
  84.  
  85.     if (addrLenPtr == (int *) NULL) {
  86.     addrLen = 0;
  87.     addrPtr = (struct sockaddr_in *) NULL;
  88.     } else {
  89.     /*
  90.      * We deal with just Internet sockets.
  91.      */
  92.  
  93.     addrLen = *addrLenPtr;
  94.     if (addrLen != sizeof(struct sockaddr_in)) {
  95.         errno = EINVAL;
  96.         return(UNIX_ERROR);
  97.     }
  98.     }
  99.  
  100.  
  101.     /*
  102.      * Tell the Inet server to accept connections on the socket.  If a
  103.      * connection is made, a token is returned that is used to convert the
  104.      * connection into a new socket.  If no connections are currently
  105.      * available and the socket is non-blocking, FS_WOULD_BLOCK is
  106.      * returned. If the socket is blockable, the ioctl returns
  107.      * NET_NO_CONNECTS so and Wait() must be used to wait for a
  108.      * connection.
  109.      */
  110.  
  111.     status = Fs_IOControl(socketID, IOC_NET_ACCEPT_CONN_1, 
  112.             0, (Address) NULL, 
  113.             sizeof(acceptToken), (Address) &acceptToken);
  114.  
  115.     switch (status) {
  116.     case SUCCESS:
  117.         break;
  118.  
  119.     case FS_WOULD_BLOCK:
  120.         errno = EWOULDBLOCK;
  121.         return(UNIX_ERROR);
  122.         break;
  123.  
  124.         case NET_NO_CONNECTS:
  125.         /*
  126.          * Wait for the server to tell us that a request has arrived.
  127.          */
  128.         (void) Wait(socketID, TRUE, (Time *) NULL);
  129.  
  130.         /*
  131.          * There's a pending connection so retry the ioctl.
  132.          */
  133.         status = Fs_IOControl(socketID, IOC_NET_ACCEPT_CONN_1, 
  134.                 0, (Address) NULL, 
  135.                 sizeof(acceptToken), (Address) &acceptToken);
  136.         if (status != SUCCESS) {
  137.         DebugMsg(status, "accept (ioctl 1b)");
  138.         errno = Compat_MapCode(status);
  139.         return(UNIX_ERROR);
  140.         }
  141.         break;
  142.  
  143.     default:
  144.         DebugMsg(status, "accept (ioctl 1a)");
  145.         errno = Compat_MapCode(status);
  146.         return(UNIX_ERROR);
  147.         break;
  148.     } 
  149.  
  150.  
  151.     /*
  152.      * Create the new socket. This socket will be converted into the new
  153.      * connection.
  154.      */
  155.  
  156.     status = Fs_Open(streamDevice, FS_READ|FS_WRITE, 0666, &newSocket);
  157.     if (status != SUCCESS) {
  158.  
  159.     DebugMsg(status, "accept (open)");
  160.     errno = Compat_MapCode(status);
  161.     return(UNIX_ERROR);
  162.     }
  163.  
  164.     /*
  165.      * Make the new socket have the same characteristics as the
  166.      * connection socket. Also, find out who we are connected to.
  167.      */
  168.     status = Fs_IOControl(newSocket, IOC_NET_ACCEPT_CONN_2, 
  169.             sizeof(acceptToken), (Address) &acceptToken, 
  170.             addrLen, (Address) addrPtr);
  171.  
  172.     if (status != SUCCESS) {
  173.     DebugMsg(status, "accept (ioctl 2)");
  174.     errno = Compat_MapCode(status);
  175.     return(UNIX_ERROR);
  176.     }
  177.     if (addrLen > 0) {
  178.     addrPtr->sin_family = AF_INET;
  179.     }
  180.  
  181.     return(newSocket);
  182. }
  183.  
  184. /*
  185.  *----------------------------------------------------------------------
  186.  *
  187.  * bind --
  188.  *
  189.  *    Assigns a local <address,port> tuple to a socket that does 
  190.  *    not have one.
  191.  *
  192.  * Results:
  193.  *    If 0        - Successful.
  194.  *    If UNIX_ERROR, then errno = 
  195.  *    EINVAL        - Bad size for *namePtr, already bound to an address.
  196.  *    EADDRINUSE    - The address is already in use.
  197.  *    EADDRNOTAVAIL    - The address is not valid for this host.
  198.  *
  199.  * Side effects:
  200.  *    The socket local address is set.
  201.  *
  202.  *----------------------------------------------------------------------
  203.  */
  204.  
  205. int
  206. bind(socketID, namePtr, nameLen)
  207.     int            socketID;    /* Stream ID of unnamed socket. */
  208.     struct sockaddr    *namePtr;    /* Local address,port for this socket.*/
  209.     int            nameLen;    /* Size of *namePtr. */
  210. {
  211.     ReturnStatus    status;
  212.  
  213.     if (nameLen != sizeof(struct sockaddr_in)) {
  214.     errno = EINVAL;
  215.     return(UNIX_ERROR);
  216.     }
  217.  
  218.     status = Fs_IOControl(socketID, IOC_NET_SET_LOCAL_ADDR, 
  219.             nameLen, (Address) namePtr, 
  220.             0, (Address) NULL);
  221.  
  222.     if (status != SUCCESS) {
  223.     DebugMsg(status, "bind");
  224.     errno = Compat_MapCode(status);
  225.     return(UNIX_ERROR);
  226.     }
  227.     return(UNIX_SUCCESS);
  228. }
  229.  
  230. /*
  231.  *----------------------------------------------------------------------
  232.  *
  233.  * connect --
  234.  *
  235.  *    For a stream socket, create a connection to a remote host.
  236.  *    For a datagram socket, only receive datagrams from this remote 
  237.  *    address.
  238.  *
  239.  * Results:
  240.  *    If 0        - Successful.
  241.  *    If UNIX_ERROR, then errno = 
  242.  *    EINVAL        - Bad size for *namePtr,
  243.  *    EADDRINUSE    - The address is already in use.
  244.  *    EADDRNOTAVAIL    - The address is not valid for this host.
  245.  *    EISCONN        - The socket is already connected.
  246.  *    ETIMEDOUT    - The connection request timed-out.
  247.  *    ECONNREFUSED    - The remote host refused the connection.
  248.  *    ENETUNREACH    - The network isn't reachable from this host.
  249.  *    EWOULDBLOCK    - If non-blocking, the connection can't be completed
  250.  *                immediately.
  251.  *    EFAULT        - Invalid argument to the ioctl.
  252.  *
  253.  * Side effects:
  254.  *    A local address for the socket is given if it did not have one 
  255.  *    already.
  256.  *
  257.  *----------------------------------------------------------------------
  258.  */
  259.  
  260. int
  261. connect(socketID, namePtr, nameLen)
  262.     int            socketID;    /* Stream ID of socket. */
  263.     struct sockaddr    *namePtr;    /* Remote address,port to connect to.*/
  264.     int            nameLen;    /* Size of *namePtr. */
  265. {
  266.     ReturnStatus    status;
  267.  
  268.     if (nameLen != sizeof(struct sockaddr_in)) {
  269.     errno = EINVAL;
  270.     return(UNIX_ERROR);
  271.     }
  272.  
  273.     status = Fs_IOControl(socketID, IOC_NET_CONNECT,
  274.             nameLen, (Address) namePtr, 
  275.             0, (Address) NULL);
  276.  
  277.     if (status == FS_WOULD_BLOCK) {
  278.     int flags = 0;
  279.     int statLen = sizeof(status);
  280.  
  281.     /*
  282.      * The connection didn't immeadiately complete, so wait if
  283.      * we're blocking or return EWOULDBLOCK if we're non-blocking.
  284.      */
  285.     status = Fs_IOControl(socketID, IOC_GET_FLAGS, 
  286.             0, (Address) NULL,
  287.             sizeof(flags), (Address) &flags);
  288.  
  289.     if (status != SUCCESS) {
  290.         DebugMsg(status, "connect (ioctl)");
  291.         panic("connect: GET_FLAGS failed.\n");
  292.     }
  293.  
  294.     if (flags & IOC_NON_BLOCKING) {
  295.         errno = EWOULDBLOCK;
  296.         return(UNIX_ERROR);
  297.     } 
  298.  
  299.     status = Wait(socketID, FALSE, &time_OneMinute);
  300.  
  301.     if (status == FS_TIMEOUT) {
  302.         DebugMsg(status, "connect (select)");
  303.         errno = ETIMEDOUT;
  304.         return(UNIX_ERROR);
  305.     }
  306.  
  307.     /*
  308.      * See if the connection successfully completed. getsockopt converts
  309.      * the status to its Unix equivalent.
  310.      */
  311.     if (getsockopt(socketID, SOL_SOCKET, SO_ERROR, (char *) &status,
  312.         &statLen) < 0) {
  313.         return(UNIX_ERROR);
  314.     }
  315.     if (status != UNIX_SUCCESS) {
  316.         errno = status;
  317.         return(UNIX_ERROR);
  318.     }
  319.     return(UNIX_SUCCESS);
  320.  
  321.     } else if (status != SUCCESS) {
  322.     DebugMsg(status, "connect");
  323.     errno = Compat_MapCode(status);
  324.     return(UNIX_ERROR);
  325.     }
  326.     return(UNIX_SUCCESS);
  327. }
  328.  
  329. /*
  330.  *----------------------------------------------------------------------
  331.  *
  332.  * getpeername --
  333.  *
  334.  *    Find out the remote address that this socket is connected to.
  335.  *
  336.  * Results:
  337.  *    If 0        - Successful.
  338.  *    If UNIX_ERROR, then errno = 
  339.  *    EINVAL        - Bad size for *namePtr.
  340.  *    ENOTCONN    - The socket is not connected.
  341.  *    EFAULT        - Invalid argument to the ioctl.
  342.  *
  343.  * Side effects:
  344.  *    None.
  345.  *
  346.  *----------------------------------------------------------------------
  347.  */
  348.  
  349. int
  350. getpeername(socketID, namePtr, nameLenPtr)
  351.     int            socketID;    /* Stream ID of socket connected to 
  352.                      * remote peer. */
  353.     struct sockaddr    *namePtr;    /* Upon return, <addr,port> for 
  354.                          * remote peer. */
  355.     int            *nameLenPtr;    /* Size of *namePtr. (in/out) */
  356. {
  357.     ReturnStatus    status;
  358.  
  359.     /*
  360.      * Make sure the struct is at least as big as an internet address.
  361.      * It can be bigger because of unions with dec net structures.
  362.      */
  363.     if (nameLenPtr == (int *) NULL ||
  364.     *nameLenPtr < sizeof(struct sockaddr_in)) {
  365.     errno = EINVAL;
  366.     return(UNIX_ERROR);
  367.     }
  368.     *nameLenPtr = sizeof(struct sockaddr_in);
  369.  
  370.     status = Fs_IOControl(socketID, IOC_NET_GET_REMOTE_ADDR, 
  371.             0, (Address) NULL, 
  372.             *nameLenPtr, (Address) namePtr);
  373.  
  374.     if (status != SUCCESS) {
  375.     DebugMsg(status, "getpeername");
  376.     errno = Compat_MapCode(status);
  377.     return(UNIX_ERROR);
  378.     }
  379.     return(UNIX_SUCCESS);
  380. }
  381.  
  382. /*
  383.  *----------------------------------------------------------------------
  384.  *
  385.  * getsockname --
  386.  *
  387.  *    Find out the local address for this socket, which was
  388.  *    set with the bind routine or by the connect routine.
  389.  *
  390.  * Results:
  391.  *    If 0        - Successful.
  392.  *    If UNIX_ERROR, then errno = 
  393.  *    EINVAL        - Bad size for *namePtr.
  394.  *    EFAULT        - Invalid argument to the ioctl.
  395.  *
  396.  * Side effects:
  397.  *    None.
  398.  *
  399.  *----------------------------------------------------------------------
  400.  */
  401.  
  402. int
  403. getsockname(socketID, namePtr, nameLenPtr)
  404.     int            socketID;    /* Stream ID of socket to get name of.*/
  405.     struct sockaddr    *namePtr;    /* Upon return, current <addr,port> for
  406.                      * this socket. */
  407.     int            *nameLenPtr;    /* Size of *namePtr. (in/out) */
  408. {
  409.     ReturnStatus    status;
  410.  
  411.     if (nameLenPtr == (int *) NULL ||
  412.     *nameLenPtr != sizeof(struct sockaddr_in)) {
  413.     errno = EINVAL;
  414.     return(UNIX_ERROR);
  415.     }
  416.  
  417.     status = Fs_IOControl(socketID, IOC_NET_GET_LOCAL_ADDR, 
  418.             0, (Address) NULL, 
  419.             *nameLenPtr, (Address) namePtr);
  420.  
  421.     if (status != SUCCESS) {
  422.     DebugMsg(status, "getsockname");
  423.     errno = Compat_MapCode(status);
  424.     return(UNIX_ERROR);
  425.     }
  426.     return(UNIX_SUCCESS);
  427. }
  428.  
  429. /*
  430.  *----------------------------------------------------------------------
  431.  *
  432.  * getsockopt --
  433.  *
  434.  *    Get the value for a socket option.
  435.  *
  436.  * Results:
  437.  *    If 0        - Successful.
  438.  *    If UNIX_ERROR, then errno = 
  439.  *    EFAULT        - Invalid argument to the ioctl.
  440.  *
  441.  * Side effects:
  442.  *    None.
  443.  *
  444.  *----------------------------------------------------------------------
  445.  */
  446.  
  447. int
  448. getsockopt(socketID, level, optName, optVal, optLenPtr)
  449.     int        socketID;    /* Stream ID of socket to get options on. */
  450.     int        level;        /* Socket or protocol level to get the option.*/
  451.     int        optName;    /* Type of option to get. */
  452.     char    *optVal;    /* Address of buffer to store the result. */
  453.     int        *optLenPtr;    /* In: Size of *optVal, out: # of bytes stored
  454.                  * in *optVal. */
  455. {
  456.     ReturnStatus    status;
  457.     int            optionsArray[2];
  458.  
  459.     /*
  460.      * OptionsArray is used to give the server the values of "level"
  461.      * and "optName". A buffer ("newBufPtr") is needed to get the option
  462.      * value and the length of the value.
  463.      */
  464.     optionsArray[0] = level;
  465.     optionsArray[1] = optName;
  466.  
  467.     status = Fs_IOControl(socketID, IOC_NET_GET_OPTION,
  468.             sizeof(optionsArray), (Address) optionsArray, 
  469.             *optLenPtr, (Address) optVal);
  470.  
  471.     if (status != SUCCESS) {
  472.     DebugMsg(status, "getsockopt");
  473.     errno = Compat_MapCode(status);
  474.     return(UNIX_ERROR);
  475.     }
  476.  
  477.     if (optName == SO_ERROR) {
  478.     /*
  479.      * The error value is a Sprite ReturnStatus so we must convert it
  480.      * to the equivalent Unix value.
  481.      */
  482.  
  483.     *(int *)optVal = Compat_MapCode(*(int *)optVal);
  484.     }
  485.  
  486.     return(UNIX_SUCCESS);
  487. }
  488.  
  489. /*
  490.  *----------------------------------------------------------------------
  491.  *
  492.  * setsockopt --
  493.  *
  494.  *    Set the value for a socket option.
  495.  *
  496.  * Results:
  497.  *    If 0        - Successful.
  498.  *    If UNIX_ERROR, then errno = 
  499.  *    EFAULT        - Invalid argument to the ioctl.
  500.  *
  501.  * Side effects:
  502.  *    None.
  503.  *
  504.  *----------------------------------------------------------------------
  505.  */
  506.  
  507. /*VARARGS  (makes lint happy) */
  508. int
  509. setsockopt(socketID, level, optName, optVal, optLen)
  510.     int        socketID;    /* Stream ID of socket to set options on. */
  511.     int        level;        /* Socket or protocol level to get the option.*/
  512.     int        optName;    /* Type of option to get. */
  513.     char    *optVal;    /* Address of buffer to store the result. */
  514.     int        optLen;        /* Size of *optVal. */
  515. {
  516.     ReturnStatus    status;
  517.     int            *newBufPtr;
  518.  
  519.     /*
  520.      * To pass the level, the type of option and the option value to the
  521.      * server, we allocate a new buffer and put the level and type in the
  522.      * first 2 slots and then copy the value to the rest of the buffer.
  523.      */
  524.     newBufPtr = (int *) malloc((unsigned) (2 * sizeof(int) + optLen));
  525.     newBufPtr[0] = level;
  526.     newBufPtr[1] = optName;
  527.     bcopy(optVal, (char *) &newBufPtr[2], optLen);
  528.  
  529.     status = Fs_IOControl(socketID, IOC_NET_SET_OPTION,
  530.             2 * sizeof(int) + optLen, (Address) newBufPtr,
  531.             0, (Address) NULL);
  532.  
  533.     free((char *) newBufPtr);
  534.  
  535.     if (status != SUCCESS) {
  536.     DebugMsg(status, "getsockopt");
  537.     errno = Compat_MapCode(status);
  538.     return(UNIX_ERROR);
  539.     }
  540.     return(UNIX_SUCCESS);
  541. }
  542.  
  543. /*
  544.  *----------------------------------------------------------------------
  545.  *
  546.  * listen --
  547.  *
  548.  *    Allows a stream socket to accept remote connection requests and to
  549.  *    specify how many such requests will be queued up before they 
  550.  *    are refused.
  551.  *
  552.  * Results:
  553.  *    If 0        - Successful.
  554.  *    If UNIX_ERROR, then errno = 
  555.  *    EOPNOTSUPP    - The socket type doesn't allow a listen operation.
  556.  *    EFAULT        - Invalid argument to the ioctl.
  557.  *
  558.  * Side effects:
  559.  *    None.
  560.  *
  561.  *----------------------------------------------------------------------
  562.  */
  563.  
  564. int
  565. listen(socketID, backlog)
  566.     int    socketID;    /* Stream ID of socket to be put in listen mode. */
  567.     int    backlog;    /* How many connection requests to queue. */
  568. {
  569.     ReturnStatus    status;
  570.  
  571.     status = Fs_IOControl(socketID, IOC_NET_LISTEN,
  572.             sizeof(backlog), (Address) &backlog, 
  573.             0, (Address) NULL);
  574.  
  575.     if (status != SUCCESS) {
  576.     DebugMsg(status, "listen");
  577.     errno = Compat_MapCode(status);
  578.     return(UNIX_ERROR);
  579.     }
  580.     return(UNIX_SUCCESS);
  581. }
  582.  
  583. /*
  584.  *----------------------------------------------------------------------
  585.  *
  586.  * recv --
  587.  *
  588.  *    Read data from a connected socket. 
  589.  *
  590.  * Results:
  591.  *    See recvfrom().
  592.  *
  593.  * Side effects:
  594.  *    None.
  595.  *
  596.  *----------------------------------------------------------------------
  597.  */
  598.  
  599. int
  600. recv(socketID, bufPtr, bufSize, flags)
  601.     int        socketID;
  602.     char    *bufPtr;    /* Address of buffer to place the data in. */
  603.     int        bufSize;    /* Size of *bufPtr. */
  604.     int        flags;        /* Type of operatrion: OR of MSG_OOB, MSG_PEEK*/
  605. {
  606.     return(recvfrom(socketID, bufPtr, bufSize, flags, 
  607.         (struct sockaddr *) NULL, (int *) NULL));
  608. }
  609.  
  610. /*
  611.  *----------------------------------------------------------------------
  612.  *
  613.  * recvfrom --
  614.  *
  615.  *    Read data from a socket.
  616.  *
  617.  * Results:
  618.  *    If 0        - Successful.
  619.  *    If UNIX_ERROR, then errno = 
  620.  *    EINVAL        - Bad size or address for senderPtr, senderLenPtr.
  621.  *    EWOULDBLOCK    - If non-blocking, no data are available.
  622.  *    EFAULT        - Invalid argument to the ioctl.
  623.  *
  624.  * Side effects:
  625.  *    None.
  626.  *
  627.  *----------------------------------------------------------------------
  628.  */
  629.  
  630. int
  631. recvfrom(socketID, bufPtr, bufSize, flags, senderPtr, senderLenPtr)
  632.     int            socketID;    /* Socket to read. */
  633.     char        *bufPtr;    /* Buffer to place the data in. */
  634.     int            bufSize;    /* Size of *bufPtr. */
  635.     int            flags;        /* Type of operatrion: OR of 
  636.                      *  MSG_OOB, MSG_PEEK*/
  637.     struct sockaddr    *senderPtr;    /* Address of sender of the data. */
  638.     int            *senderLenPtr;    /* Size of *senderPtr. (in/out) */
  639. {
  640.     ReturnStatus    status;
  641.     int            amountRead;
  642.  
  643.     if (senderPtr != (struct sockaddr *) NULL) {
  644.     if ((senderLenPtr == (int *) NULL) ||
  645.         (*senderLenPtr != sizeof(struct sockaddr_in))) {
  646.         errno = EINVAL;
  647.         return(UNIX_ERROR);
  648.     }
  649.     }
  650.  
  651.     /*
  652.      * If there are flags, ship them to the server.
  653.      */
  654.     if (flags != 0) {
  655.     status = Fs_IOControl(socketID, IOC_NET_RECV_FLAGS,
  656.                 sizeof(flags), (Address) &flags, 
  657.                 0, (Address) NULL);
  658.     if (status != SUCCESS) {
  659.         DebugMsg(status, "recvfrom (ioctl recv_flags)");
  660.         errno = Compat_MapCode(status);
  661.         return(UNIX_ERROR);
  662.     }
  663.     }
  664.  
  665.     status = Fs_Read(socketID, bufSize, bufPtr, &amountRead);
  666.     if (status != SUCCESS) {
  667.     DebugMsg(status, "recvfrom (read)");
  668.     errno = Compat_MapCode(status);
  669.     return(UNIX_ERROR);
  670.     }
  671.  
  672.     /*
  673.      * If the caller wants the address of the sender, ask the server for it.
  674.      */
  675.     if (senderPtr != (struct sockaddr *) NULL) {
  676.     status = Fs_IOControl(socketID, IOC_NET_RECV_FROM,
  677.                 0, (Address) NULL,
  678.                 *senderLenPtr, (Address) senderPtr);
  679.     if (status != SUCCESS) {
  680.         DebugMsg(status, "recvfrom (ioctl get_remote)");
  681.         errno = Compat_MapCode(status);
  682.         return(UNIX_ERROR);
  683.     }
  684.     }
  685.     return(amountRead);
  686. }
  687.  
  688. /*
  689.  *----------------------------------------------------------------------
  690.  *
  691.  * recvmsg --
  692.  *
  693.  *    Read data from a socket using multiple buffers.
  694.  *
  695.  * Results:
  696.  *    If 0        - Successful.
  697.  *    If UNIX_ERROR, then errno = 
  698.  *    EINVAL        - Bad size or address for msg_name, msg_namelen;
  699.  *                I/O vector length too big.
  700.  *    EWOULDBLOCK    - If non-blocking, no data are available.
  701.  *    EFAULT        - Invalid argument to the ioctl, null address 
  702.  *               for msgPtr.
  703.  *
  704.  * Side effects:
  705.  *    None.
  706.  *
  707.  *----------------------------------------------------------------------
  708.  */
  709.  
  710. int
  711. recvmsg(socketID, msgPtr, flags)
  712.     int            socketID;    /* Sokect to read data from. */
  713.     struct msghdr    *msgPtr;    /* I/O vector of buffers to store the
  714.                      * data. */
  715.     int            flags;        /* Type of operatrion: OR of 
  716.                      *  MSG_OOB, MSG_PEEK*/
  717. {
  718.     ReturnStatus    status;
  719.     int            amountRead;
  720.  
  721.  
  722.     if (msgPtr == (struct msghdr *) NULL) {
  723.     errno = EFAULT;
  724.     return(UNIX_ERROR);
  725.     }
  726.  
  727.     if (msgPtr->msg_name != (Address) NULL) {
  728.     if (msgPtr->msg_namelen != sizeof(struct sockaddr_in)) {
  729.         errno = EINVAL;
  730.         return(UNIX_ERROR);
  731.     }
  732.     }
  733.  
  734.     if (msgPtr->msg_iovlen > MSG_MAXIOVLEN) {
  735.     errno = EINVAL;
  736.     return(UNIX_ERROR);
  737.     }
  738.  
  739.     /*
  740.      * If there are flags, ship them to the server.
  741.      */
  742.     if (flags != 0) {
  743.     status = Fs_IOControl(socketID, IOC_NET_RECV_FLAGS,
  744.                 sizeof(flags), (Address) &flags, 
  745.                 0, (Address) NULL);
  746.     if (status != SUCCESS) {
  747.         DebugMsg(status, "recvmsg (ioctl recv_flags)");
  748.         errno = Compat_MapCode(status);
  749.         return(UNIX_ERROR);
  750.     }
  751.     }
  752.  
  753.     amountRead = readv(socketID, msgPtr->msg_iov, msgPtr->msg_iovlen);
  754.     if (amountRead < 0) {
  755.     DebugMsg(errno, "recvmsg (readv)");
  756.     }
  757.     
  758.     /*
  759.      * If the caller wants the address of the sender, ask the server for it.
  760.      */
  761.     if (msgPtr->msg_name != (Address) NULL) {
  762.     status = Fs_IOControl(socketID, IOC_NET_RECV_FROM,
  763.             0, (Address) NULL,
  764.             msgPtr->msg_namelen, (Address) msgPtr->msg_name);
  765.     if (status != SUCCESS) {
  766.         DebugMsg(status, "recvmsg (ioctl recv_from)");
  767.         errno = Compat_MapCode(status);
  768.         return(UNIX_ERROR);
  769.     }
  770.     }
  771.  
  772.     return(amountRead);
  773. }
  774.  
  775. /*
  776.  *----------------------------------------------------------------------
  777.  *
  778.  * send --
  779.  *
  780.  *    Write data to a connected socket.
  781.  *
  782.  * Results:
  783.  *    See sendto().
  784.  *
  785.  * Side effects:
  786.  *    None.
  787.  *
  788.  *----------------------------------------------------------------------
  789.  */
  790.  
  791. int
  792. send(socketID, bufPtr, bufSize, flags)
  793.     int        socketID;    /* Socket to send data on. */
  794.     char    *bufPtr;    /* Address of buffer to send. */
  795.     int        bufSize;    /* Size of *bufPtr. */
  796.     int        flags;        /* Type of operatrion: OR of 
  797.                  *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  798. {
  799.     return(sendto(socketID, bufPtr, bufSize, flags,(struct sockaddr *)NULL, 0));
  800. }
  801.  
  802. /*
  803.  *----------------------------------------------------------------------
  804.  *
  805.  * sendto --
  806.  *
  807.  *    Send a message from a socket.
  808.  *
  809.  * Results:
  810.  *    If 0        - Successful.
  811.  *    If UNIX_ERROR, then errno = 
  812.  *    EINVAL        - Bad size or address for destPtr, destLen..
  813.  *    EWOULDBLOCK    - If non-blocking, the server buffers are too
  814.  *              full to accept the data.
  815.  *    EMSGSIZE    - The buffer is too large to be sent in 1 packet.
  816.  *    EFAULT        - Invalid argument to the ioctl.
  817.  *
  818.  * Side effects:
  819.  *    None.
  820.  *
  821.  *----------------------------------------------------------------------
  822.  */
  823.  
  824. int
  825. sendto(socketID, bufPtr, bufSize, flags, destPtr, destLen)
  826.     int        socketID;    /* Socket to send data on. */
  827.     char    *bufPtr;    /* Address of buffer to send. */
  828.     int        bufSize;    /* Size of *bufPtr. */
  829.     int        flags;        /* Type of operatrion: OR of 
  830.                  *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  831.     struct sockaddr    *destPtr;    /* Destination to send the data to. */
  832.     int            destLen;    /* Size of *destPtr.  */
  833. {
  834.     ReturnStatus    status;
  835.     int            numWritten;
  836.  
  837.     /*
  838.      * If either the flags or a destination are given, send them to the server.
  839.      */
  840.     if ((flags != 0) || (destPtr != (struct sockaddr *) NULL)) {
  841.     Net_SendInfo    sendInfo;
  842.  
  843.     if (destPtr != (struct sockaddr *) NULL) {
  844.         if (destLen != sizeof(struct sockaddr_in)) {
  845.         errno = EINVAL;
  846.         return(UNIX_ERROR);
  847.         }
  848.         sendInfo.addressValid = TRUE;
  849.         sendInfo.address.inet = *(Net_InetSocketAddr *) destPtr;
  850.     } else {
  851.         sendInfo.addressValid = FALSE;
  852.     }
  853.     sendInfo.flags = flags;
  854.  
  855.     status = Fs_IOControl(socketID, IOC_NET_SEND_INFO,
  856.             sizeof(sendInfo), (Address) &sendInfo, 
  857.             0, (Address) NULL);
  858.     if (status != SUCCESS) {
  859.         DebugMsg(status, "sendto (ioctl)");
  860.         errno = Compat_MapCode(status);
  861.         return(UNIX_ERROR);
  862.     }
  863.     }
  864.  
  865.     status = Fs_Write(socketID, bufSize, bufPtr, &numWritten);
  866.     if (status != SUCCESS) {
  867.     DebugMsg(status, "sendto (write)");
  868.     errno = Compat_MapCode(status);
  869.     return(UNIX_ERROR);
  870.     }
  871.     return(numWritten);
  872. }
  873.  
  874. /*
  875.  *----------------------------------------------------------------------
  876.  *
  877.  * sendmsg --
  878.  *
  879.  *    Send a message from a socket.
  880.  *
  881.  * Results:
  882.  *    If 0        - Successful.
  883.  *    If UNIX_ERROR, then errno = 
  884.  *    EINVAL        - Bad size or address for msg_name, msg_namelen;
  885.  *                I/O vector length too big.
  886.  *    EWOULDBLOCK    - If non-blocking, the server buffers are too full 
  887.  *              accept the data.
  888.  *    EFAULT        - Invalid argument to the ioctl, null address 
  889.  *               for msgPtr.
  890.  *
  891.  * Side effects:
  892.  *    None.
  893.  *
  894.  *----------------------------------------------------------------------
  895.  */
  896.  
  897. int
  898. sendmsg(socketID, msgPtr, flags)
  899.     int            socketID;    /* Socket to send data on. */
  900.     struct msghdr    *msgPtr;    /* I/O vector of buffers containing
  901.                      * data to send. */
  902.     int            flags;        /* Type of operatrion: OR of 
  903.                      *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  904. {
  905.     ReturnStatus    status;
  906.     int            numWritten;
  907.  
  908.     if (msgPtr == (struct msghdr *) NULL) {
  909.     errno = EFAULT;
  910.     return(UNIX_ERROR);
  911.     }
  912.  
  913.     if (msgPtr->msg_iovlen > MSG_MAXIOVLEN) {
  914.     errno = EINVAL;
  915.     return(UNIX_ERROR);
  916.     }
  917.     
  918.     if ((flags != 0) || (msgPtr->msg_name != (Address) NULL)) {
  919.     Net_SendInfo    sendInfo;
  920.  
  921.     if (msgPtr->msg_name != (Address) NULL) {
  922.         if (msgPtr->msg_namelen != sizeof(struct sockaddr_in)) {
  923.         errno = EINVAL;
  924.         return(UNIX_ERROR);
  925.         }
  926.         sendInfo.addressValid = TRUE;
  927.         sendInfo.address.inet = *(Net_InetSocketAddr *)msgPtr->msg_name;
  928.     } else {
  929.         sendInfo.addressValid = FALSE;
  930.     }
  931.     sendInfo.flags = flags;
  932.  
  933.     status = Fs_IOControl(socketID, IOC_NET_SEND_INFO,
  934.                 sizeof(sendInfo), (Address) &sendInfo, 
  935.                 0, (Address) NULL);
  936.  
  937.     if (status != SUCCESS) {
  938.         DebugMsg(status, "sendmsg (ioctl)");
  939.         errno = Compat_MapCode(status);
  940.         return(UNIX_ERROR);
  941.     }
  942.     }
  943.  
  944.     numWritten = writev(socketID, msgPtr->msg_iov, msgPtr->msg_iovlen);
  945.     if (numWritten < 0) {
  946.     DebugMsg(errno, "sendmsg (writev)");
  947.     }
  948.     return(numWritten);
  949. }
  950.  
  951. /*
  952.  *----------------------------------------------------------------------
  953.  *
  954.  * socket --
  955.  *
  956.  *    Create a socket in the Internet domain.
  957.  *
  958.  * Results:
  959.  *    If > 0, the stream ID of the new socket.
  960.  *    If UNIX_ERROR, then errno = 
  961.  *    EINVAL        - "domain" did not specify the Internet domain.
  962.  *    ?        - Error from Fs_Open, Fs_IOControl.
  963.  *
  964.  * Side effects:
  965.  *    A new stream is created.
  966.  *
  967.  *----------------------------------------------------------------------
  968.  */
  969.  
  970. int
  971. socket(domain, type, protocol)
  972.     int    domain;        /* Type of communications domain */
  973.     int    type;        /* Type of socket: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW. */
  974.     int    protocol;    /* Specific protocol to use. */
  975. {
  976.     ReturnStatus    status;
  977.     int            streamID;
  978.  
  979.     if (domain != PF_INET) {
  980.     errno = EINVAL;
  981.     return(UNIX_ERROR);
  982.     }
  983.  
  984.     if (!gotHostName) {
  985.     gotHostName = TRUE;
  986.     if (gethostname(myHostName, sizeof(myHostName)) != 0) {
  987.         panic("socket: Can't find my hostname\n");
  988.     }
  989.     sprintf(streamDevice, INET_STREAM_NAME_FORMAT, myHostName);
  990.     sprintf(dgramDevice, INET_DGRAM_NAME_FORMAT, myHostName);
  991.     sprintf(rawDevice, INET_RAW_NAME_FORMAT, myHostName);
  992.     }
  993.  
  994.     if (type == SOCK_STREAM) {
  995.     status = Fs_Open(streamDevice, FS_READ|FS_WRITE, 0666, &streamID);
  996.     if (status != SUCCESS) {
  997.         DebugMsg(status, "socket (stream)");
  998.         errno = Compat_MapCode(status);
  999.         return(UNIX_ERROR);
  1000.     }
  1001.     } else if (type == SOCK_DGRAM) {
  1002.     status = Fs_Open(dgramDevice, FS_READ|FS_WRITE, 0666, &streamID);
  1003.     if (status != SUCCESS) {
  1004.         DebugMsg(status, "socket (datagram)");
  1005.         errno = Compat_MapCode(status);
  1006.         return(UNIX_ERROR);
  1007.     }
  1008.     } else if (type == SOCK_RAW) {
  1009.     status = Fs_Open(rawDevice, FS_READ|FS_WRITE, 0666, &streamID);
  1010.     if (status != SUCCESS) {
  1011.         DebugMsg(status, "socket (raw)");
  1012.         errno = Compat_MapCode(status);
  1013.         return(UNIX_ERROR);
  1014.     }
  1015.     } else {
  1016.     errno = EINVAL;
  1017.     return(UNIX_ERROR);
  1018.     }
  1019.  
  1020.     if (protocol != 0) {
  1021.     status = Fs_IOControl(streamID, IOC_NET_SET_PROTOCOL,
  1022.                 sizeof(protocol), (Address) &protocol, 
  1023.                 0, (Address) NULL);
  1024.     if (status != SUCCESS) {
  1025.         DebugMsg(status, "socket (ioctl)");
  1026.         errno = Compat_MapCode(status);
  1027.         return(UNIX_ERROR);
  1028.     }
  1029.     }
  1030.  
  1031.     return(streamID);
  1032. }
  1033.  
  1034. /*
  1035.  *----------------------------------------------------------------------
  1036.  *
  1037.  * shutdown --
  1038.  *
  1039.  *    Shut down part of a full-duplex connection.
  1040.  *
  1041.  * Results:
  1042.  *    0        - The action was successful.
  1043.  *
  1044.  * Side effects:
  1045.  *    None.
  1046.  *
  1047.  *----------------------------------------------------------------------
  1048.  */
  1049.  
  1050. int
  1051. shutdown(socketID, action)
  1052.     int        socketID;    /* Socket to shut down. */
  1053.     int        action;        /* 0 -> disallow further recvs, 
  1054.                  * 1 -> disallow further sends,
  1055.                  * 2 -> combination of above. */
  1056. {
  1057.     ReturnStatus    status;
  1058.  
  1059.     status = Fs_IOControl(socketID, IOC_NET_SHUTDOWN, 
  1060.             sizeof(action), (Address) &action, 
  1061.             0, (Address) NULL);
  1062.  
  1063.     if (status != SUCCESS) {
  1064.     DebugMsg(status, "shutdown");
  1065.     errno = Compat_MapCode(status);
  1066.     return(UNIX_ERROR);
  1067.     }
  1068.     return(UNIX_SUCCESS);
  1069. }
  1070.  
  1071.  
  1072. /*
  1073.  *----------------------------------------------------------------------
  1074.  *
  1075.  * Wait --
  1076.  *
  1077.  *    Wait for the Inet server to indicate that a socket is ready
  1078.  *    for some action.
  1079.  *
  1080.  * Results:
  1081.  *    SUCCESS, or FS_TIMEOUT if a timeout occurred.
  1082.  *
  1083.  * Side effects:
  1084.  *    None.
  1085.  *
  1086.  *----------------------------------------------------------------------
  1087.  */
  1088.  
  1089. static ReturnStatus
  1090. Wait(socketID, readSelect, timeOutPtr)
  1091.     int     socketID;    /* Socket to wait on. */
  1092.     Boolean    readSelect;    /* If TRUE, select for reading, else select for
  1093.                  *  writing. */
  1094.     Time    *timeOutPtr;    /* Timeout to use for select. */
  1095. {
  1096.     ReturnStatus    status;
  1097.     int            numReady;
  1098.  
  1099.     /*
  1100.      * Wait until the Inet server indicates the socket is ready.
  1101.      */
  1102.  
  1103.     if (socketID < 32) {
  1104.     int    mask;
  1105.  
  1106.     mask = 1 << socketID;
  1107.     if (readSelect) {
  1108.         status = Fs_Select(socketID, timeOutPtr, &mask, 
  1109.                     (int *) NULL, (int *) NULL, &numReady);
  1110.     } else {
  1111.         status = Fs_Select(socketID, timeOutPtr, (int *) NULL, 
  1112.                     &mask, (int *) NULL, &numReady);
  1113.     }
  1114.     } else {
  1115.     int    *maskPtr;
  1116.  
  1117.     Bit_Alloc(socketID, maskPtr);
  1118.     Bit_Set(socketID, maskPtr);
  1119.  
  1120.     if (readSelect) {
  1121.         status = Fs_Select(socketID, timeOutPtr, maskPtr, 
  1122.                     (int *) NULL, (int *) NULL, &numReady);
  1123.     } else {
  1124.         status = Fs_Select(socketID, timeOutPtr, (int *) NULL,
  1125.                     maskPtr, (int *) NULL, &numReady);
  1126.     }
  1127.     free((char *) maskPtr);
  1128.     }
  1129.  
  1130.     if (status == FS_TIMEOUT) {
  1131.     return(status);
  1132.     } else if (status != SUCCESS) {
  1133.     Stat_PrintMsg(status, "Wait (socket.c)");
  1134.     panic("Wait (socket.c): Fs_Select failed.\n");
  1135.     }
  1136.  
  1137.     if (numReady != 1) {
  1138.     /*
  1139.      * This is a hack around a kernel bug 12/15/90 that should go away soon.
  1140.      * The problem is that Fs_Select returns SUCCESS, when it means TIMEOUT.
  1141.      * The way to distinguish this is by numReady != 1.
  1142.      */
  1143. #if 1
  1144.     return(FS_TIMEOUT);
  1145. #else
  1146.     panic("Wait (socket.c): Fs_Select returned %d ready\n",
  1147.                 numReady);
  1148. #endif
  1149.     }
  1150.  
  1151.     return(SUCCESS);
  1152. }
  1153.